[HBase]08 Phoenix二级索引 八

全局索引、本地索引

Posted by 李玉坤 on 2017-10-15

Phoenix二级索引官网:http://phoenix.apache.org/secondary_indexing.html

建表和建索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
建表:
0: jdbc:phoenix:> select * from my_schema.my_table;
+-----+--------------------------+------+
| ID | DATE | SEX |
+-----+--------------------------+------+
| 1 | 2020-03-31 00:00:00.000 | 男 |
| 2 | 2020-02-28 00:00:00.000 | 2 |
| 3 | 2020-02-28 00:00:00.000 | 2 |
+-----+--------------------------+------+
3 rows selected (0.102 seconds)


20个region
CREATE TABLE my_schema.my_table ( id BIGINT not null primary key, date VARCHAR,sex varchar(10)) salt_buckets = 20;

1个region
CREATE TABLE my_schema.my_table ( id BIGINT not null primary key, date VARCHAR,sex varchar(10)) ;

4个region region:3+1=4
CREATE TABLE my_schema.my_table ( id BIGINT not null primary key, date VARCHAR,sex varchar(10)) split(1,2,3) ;【不会像盐表一样有随机数前缀】

建索引:

全局索引
CREATE INDEX my_index ON my_schema.my_table(sex,date);

全局索引

语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
创建索引
CREATE INDEX my_index ON my_schema.my_table(sex,date);

0: jdbc:phoenix:> CREATE INDEX my_index ON my_schema.my_table(sex,date);
3 rows affected (6.432 seconds)
0: jdbc:phoenix:> select * from my_schema.my_index;
+--------+-------------+------+
| 0:SEX | 0:DATE | :ID |
+--------+-------------+------+
| 0 | 2020-03-11 | 4 |
| 2 | 2020-03-23 | 2 |
| 2 | 2020-03-20 | 3 |
| 1 | 2020-05-31 | 1 |
+--------+-------------+------+

删除索引
DROP INDEX my_index ON my_schema.my_table;

全局索引就是盐表index

全局索引本质:就是一张表,对于使用该索引,在查询条件的字段如果不在indextable里,就默认不走index;除非使用hint 强制(强制走索引)

业务: 重读轻写 写的QPS没有读的QPS高

如果有where条件,客户端的最佳读取顺序
client –》index table –》data table

1
2
3
4
5
6
7
8
9
10
11
全表扫描 all:
走数据表:explain select * from ruozedata.testsalt;
走数据表:explain select /*+ INDEX(ruozedata.testsalt testsalt_idx) */ * from ruozedata.testsalt;【使用hint强制】

explain select date from my_schema.my_table where sex='2'; 范围扫描
走索引表:RANGE SCAN OVER MY_SCHEMA:MY_INDEX2 ['2'] 【如果建表默认一个region不加盐】
走索引表:RANGE SCAN OVER MY_SCHEMA:MY_INDEX2 [0,'2'] - [19,'2'] 【如果建表设定20个region】

explain select sex from my_schema.my_table where date='2020-05-31';
走索引表:FULL SCAN OVER MY_SCHEMA.MY_INDEX 【如果建表默认一个region不加盐】全扫描
走索引表:RANGE SCAN OVER MY_SCHEMA:MY_INDEX [0] - [19] 【如果建表设定20个region】

如果再给表加上一列col4,根据col4查询可以看出查询计划是FULL SCAN 数据表,因为col4不在索引表里。

1
2
3
4
5
6
7
alter table my_schema.my_table add col4 varchar(10);

upsert into my_schema.my_table(id, date,sex,col4) values (1,'2020-03-31','1','5');

走数据表:explain select sex from my_schema.my_table where col4='5';
走数据表:explain select date,col4 from my_schema.my_table where sex='5';
先走索引表查出rowkey再走数据表:explain select /*+ INDEX(my_schema.my_table my_index) */ date,col4 from my_schema.my_table where sex='5';

总结:
where条件全部是索引字段,select条件全部是索引字段,最优的
where条件全部是索引字段,select条件不部是索引字段,为了走index,强制走

建议:没事多看看执行计划 对应去调整

本地索引

适用于业务: 重写轻读
本质:就是一个cf, 是index数据和原数据存储在同一个表里,在原来数据表中多了一个cf;对于本地索引,查询中无论使用hint强制指定 或者 查询列是否都在index表里,都默认使用索引表。

语法

1
2
3
4
5
创建索引
CREATE LOCAL INDEX my_index ON my_schema.my_table(sex,date);

删除索引
DROP INDEX my_index ON my_schema.my_table;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
全表扫描 all:
explain select * from my_schema.my_table;
explain select /*+ INDEX(my_schema.my_table my_index) */ * from ruozedata.testsalt;

走index,RANGE SCAN
explain select date from my_schema.my_table where sex=1;
走index,RANGE SCAN
explain select date,col4 from my_schema.my_table where sex=1;


走index,RANGE SCAN
explain select col4 from my_schema.my_table where sex=1;

强制,走index
explain select /*+ INDEX(my_schema.my_table my_index) */ col4 from my_schema.my_table where sex=1;

全表扫描
explain select /*+ INDEX(my_schema.my_table my_index) */ col4 from my_schema.my_table ;
  • 总结: 要有where条件,且字段不要以*
  • 好处:写的性能高 无需写index table ,其实实际上是没有index table这个概念
  • 坏处:在使用本地索引时,必须检查所有的region的数据,因为无法先确定索引数据的准确区域位置,所以读的开销较大。

全局索引与本地索引 两者对比:全局是表 重读轻写 ,本地是CF 重写轻读

假如不清楚业务场景 模糊;建议使用 盐表和全局索引,为什么?
1.盐表 语法简单 【split 还要考虑主键范围的划分】
2.写的性能 没有读的高,我们生产上QPS 写的在5W/s